#include "graph.h"
#include <stdlib.h>
void run(int number_of_clusters)
{
	int edges_cnt, vertexes_cnt, i,j, constraints_cnt = 0, three_k_e, x;
	int numcols,numrows, objsen;
	double * obj, *rhs, *matval, *lb, *ub, *rngval;
	int * arr_deg;
	int *track_arr;
	int *matbeg, *matcnt, *matind;
	char * sense;
	edges_cnt = get_number_of_edges();
	vertexes_cnt = get_number_of_vertex();

	numcols = number_of_clusters * (edges_cnt + vertexes_cnt); //NUM_OF_VARS
	numrows = 3 * number_of_clusters * edges_cnt + vertexes_cnt  + number_of_clusters; //nUM_OF_CONSTRAINTS
	objsen  =0; //TODO:  CPX_MAX
	obj = (double*)calloc(numcols, sizeof(double));
	sense = (char*)malloc(sizeof(char) * numcols);
	rhs = (double*)malloc(sizeof(double) * numcols);
	matbeg = (int*)malloc(sizeof(int) * numcols);
	matcnt = (int*)malloc(sizeof(int) * numcols);
	matval = (double*)malloc(sizeof(double) * (7* number_of_clusters *edges_cnt +  2*number_of_clusters *vertexes_cnt ));
	
	matind = (int*)malloc(sizeof(int) * (7* number_of_clusters *edges_cnt +  2*number_of_clusters *vertexes_cnt ));
	three_k_e = 3 * edges_cnt * number_of_clusters;
	arr_deg = (int*)calloc(get_number_of_vertex(), sizeof(int));
	//TODO: Asserts!!!

	/*Now buiding an array, holding for place i, the degree of vertex i */

	for(i = 0; i < get_number_of_edges(); i++)
	{
		arr_deg[get_edges()[i]->v1_id]++;
		arr_deg[get_edges()[i]->v2_id]++;
	}

	for (i = 0 ; i <edges_cnt ; i++)
	{
		for (j= 0; j <  number_of_clusters;j++)
		{
			obj[i * number_of_clusters + j] = get_edges()[i]->weight;
		}
	}

	//assigning the first K*e mat_cnt
	for (i = 0 ; i < edges_cnt ; i++)
	{
		for (j = 0 ; j <number_of_clusters ; j++)
		{
			matcnt[number_of_clusters * i + j] = 3;
		}
	}

	//assigning the rest v* k mat_cnt
	for (i = 0 ; i <  vertexes_cnt ; i++)
	{
		for (j = 0 ; j <number_of_clusters; j++)
		{
			matcnt[(number_of_clusters * edges_cnt) + number_of_clusters* i + j] = arr_deg[i] * 2 + 2;
		}
	}

	//Now assigning the matbeg by the mat_cnt array
	matbeg[0] = 0;
	for (i = 1 ; i < numcols ; i++)
	{
		matbeg[i] = matcnt[i-1] + matbeg[i-1];
	}


	/* assigning matind & matval */

	for (i = 0 ; i < three_k_e ; i++)
	{
		matval[i] = 1;
	}

	constraints_cnt = 0;
	for (i = 0 ; i < vertexes_cnt  ; i++)
	{
		 for (j = 0 ; j < number_of_clusters ; j++)
		 {
			 for (x= 0 ; x < arr_deg[i] * 2 ; x++)
			 {
				 matval[three_k_e + constraints_cnt] = -1;
				 constraints_cnt++;
			 }

			 matval[three_k_e + constraints_cnt] =1;
			 constraints_cnt++;
			 matval[three_k_e  + constraints_cnt] = 1;
			 constraints_cnt++;
		 }
	}
	
	constraints_cnt = 0;
	track_arr = (int *)calloc(sizeof(int) , numcols);
	for(i= 0; i < edges_cnt ; i++)
	{
		for (j= 0; j < number_of_clusters; j++)
		{
			int iv1, iv2;
			matind[3* (i * number_of_clusters + j)] = number_of_clusters * (i * number_of_clusters + j); //0,2,4,
			matind[3* (i * number_of_clusters + j) + 1] = number_of_clusters * (i * number_of_clusters + j) + 1; //1,3,5
			matind[3* (i * number_of_clusters + j) +2] = 2 * number_of_clusters * edges_cnt + (i * number_of_clusters + j) ;// K + 0, k + 1, k +2

			//matind[matbeg[edges_cnt * number_of_clusters] + constraints_cnt] = i * number_of_clusters + j;

			iv1 = number_of_clusters * edges_cnt + get_edges()[i]->v1_id*number_of_clusters + j;
			iv2 = number_of_clusters * edges_cnt + get_edges()[i]->v2_id*number_of_clusters + j;
			
			matind[matbeg[iv1] + track_arr[iv1]] = number_of_clusters * (i * number_of_clusters + j);
			track_arr[iv1]++;
			
			matind[matbeg[iv2] + track_arr[iv2]] = number_of_clusters * (i * number_of_clusters + j) + 1;
			track_arr[iv2]++;
			
		}
	}

	for(i= 0; i < edges_cnt ; i++)
	{
		for (j= 0; j < number_of_clusters; j++)
		{
			int iv1, iv2;

			iv1 = number_of_clusters * edges_cnt + get_edges()[i]->v1_id*number_of_clusters + j;
			iv2 = number_of_clusters * edges_cnt + get_edges()[i]->v2_id*number_of_clusters + j;
			matind[matbeg[iv1] + track_arr[iv1]] = 2 * number_of_clusters * edges_cnt + (i * number_of_clusters + j) ;
			track_arr[iv1]++;
			matind[matbeg[iv2] + track_arr[iv2]] = 2 * number_of_clusters * edges_cnt + (i * number_of_clusters + j) ;		
			track_arr[iv2]++;
		}
	}

	for (i = 0 ; i < vertexes_cnt ; i++)
	{
		for (j = 0 ; j < number_of_clusters ; j++)
		{
			matind[matbeg[number_of_clusters * edges_cnt + i * number_of_clusters + j ]  + matcnt[number_of_clusters * edges_cnt + i * number_of_clusters + j] - 2] = three_k_e + i;
			matind[matbeg[number_of_clusters * edges_cnt + i * number_of_clusters + j ]  + matcnt[number_of_clusters * edges_cnt + i * number_of_clusters + j] - 1] = three_k_e + vertexes_cnt + j; 
		}
	}
	for (i = 0 ; i<2*number_of_clusters*edges_cnt;++i){
		rhs[i]=0;
		sense[i]='L';	
	}
	for (i=i ; i<3*number_of_clusters*edges_cnt;++i){
		rhs[i]=-1;
		sense[i]='G';	
	}

	for (i = three_k_e ; i < three_k_e + vertexes_cnt ; i++)
	{
		rhs[i] = 1;
		sense[i] = 'E';
	}
	for (i =  three_k_e  + vertexes_cnt ; i < three_k_e  + vertexes_cnt  + number_of_clusters ; i++)
	{
		rhs[i] = 1;
		sense[i] = 'G';
	}

	free(obj);
	//TODO:More frees!!@!FF
}